이전 글목록 보기다음 글
docker2026-02-22T06:53:33.927Z

Docker 완전 백업 방법

peanut2026 profilepeanut2026
docker.svg

🐳 Docker 환경 전체 백업 & 복구 가이드

Docker 기반 멀티 서비스 환경에서 DB + Volume + 메타데이터 + 프로젝트 파일을 체계적으로 백업하고,
USB 외부 매체로 안전하게 옮기며, 필요 시 새 서버에서 완전 복구하는 방법을 정리합니다.


📑 목차

  • 1. 백업 대상

  • 2. 통합 백업 스크립트

  • 3. 설정 & 실행

  • 4. 자동화 & 보관 정책

  • 5. 복구 방법

  • 6. USB 외부 백업

  • 7. 주의사항 & 팁

  • 8. 백업 검증


1. 백업 대상

📦 PostgreSQL 컨테이너

  • my-app-db-prod

  • my-app-db-dev

  • my-site-db

  • my-service-db-dev

📦 MySQL 컨테이너

  • my-mysql-01

  • my-mysql-02

📦 Docker Volumes

project_a_db_data
project_a_wordpress_data
my-app-infra_postgres_data_dev
my-app-infra_redis_data_dev
my-app_backups
my-app_postgres_data
my-app_redis_data
my-app_uploads
other-app_postgres_dev_data
my-site_postgres_data
nextcloud_data
project_b_db_data
project_b_wordpress_data


👉 특히 nextcloud_data, my-app_uploads, wordpress_data 는 파일데이터라 반드시 백업 필요.

📦 백업 전략 요약

항목

이유

백업 방식

DB (PostgreSQL / MySQL)

논리백업 필수 — Volume 복사만으로는 깨질 수 있음

pg_dumpall / mysqldump

Docker Volume

실제 서비스 데이터 저장 위치

Alpine 임시 컨테이너 + tar

Docker 메타정보

컨테이너 설정 / 네트워크 / 이미지 목록

docker inspect

사용자 파일

docker-compose, nginx, SSL 인증서 등

/home/your-user tar 압축

Docker 이미지

다시 pull 가능 → 백업 불필요

제외


2. 통합 백업 스크립트

📄 /root/docker-full-backup.sh — 이 스크립트 하나로 전체 백업을 수행합니다.

#!/bin/bash

set -e

DATE=$(date +%F-%H%M)
BASE="/backup/$DATE"

echo "=================================================="
echo " Docker Full Backup Start : $DATE"
echo "=================================================="

mkdir -p $BASE/{postgres,mysql,volumes,meta}

########################################
# 1️⃣ PostgreSQL Logical Backup
########################################

echo "[1/5] Backing up PostgreSQL..."

PG_CONTAINERS=(
my-app-db-prod
my-app-db-dev
my-site-db
my-service-db-dev
)

for C in "${PG_CONTAINERS[@]}"; do
echo " -> Processing $C"

PGUSER=$(docker inspect $C \
 | grep POSTGRES_USER \
 | head -n1 \
 | cut -d= -f2 \
 | tr -d '",')

if [ -z "$PGUSER" ]; then
echo " ERROR: POSTGRES_USER not found in $C"
exit 1
fi

echo " Using DB User: $PGUSER"

docker exec $C pg_dumpall -U "$PGUSER" \
 > $BASE/postgres/$C.sql
done

echo " PostgreSQL backup completed."

########################################
# 2️⃣ MySQL Logical Backup
########################################

echo "[2/5] Backing up MySQL..."

docker exec my-mysql-01 mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --all-databases \
 > $BASE/mysql/my-mysql-01.sql

docker exec my-mysql-02 mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --all-databases \
 > $BASE/mysql/my-mysql-02.sql

echo " MySQL backup completed."

########################################
# 3️⃣ Docker Volume Backup
########################################

echo "[3/5] Backing up Docker Volumes..."

for VOLUME in $(docker volume ls -q); do
echo " -> $VOLUME"

docker run --rm \
 -v ${VOLUME}:/volume \
    -v $BASE/volumes:/backup \
    alpine \
    tar czf /backup/${VOLUME}.tar.gz -C /volume .
done

echo " Volume backup completed."

########################################
# 4️⃣ Docker Metadata Backup
########################################

echo "[4/5] Saving Docker metadata..."

docker ps -a > $BASE/meta/container-list.txt
docker inspect $(docker ps -aq) > $BASE/meta/docker-inspect.json
docker volume ls > $BASE/meta/volume-list.txt
docker network ls > $BASE/meta/network-list.txt
docker images > $BASE/meta/image-list.txt

echo " Metadata backup completed."

########################################
# 5️⃣ Project Files Backup
########################################

echo "[5/5] Backing up /home/your-user ..."

tar czf $BASE/meta/home-backup.tar.gz /home/your-user

echo " Project files backup completed."

########################################

echo "=================================================="
echo " Docker Full Backup SUCCESS : $BASE"
echo "=================================================="

########################################
# 6️⃣ Remove Old Backups (30일 보관)
########################################

echo "Cleaning backups older than 30 days..."

find /backup -mindepth 1 -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \;

echo "Old backup cleanup completed."

3. 설정 & 실행

3-1. 디렉토리 & 권한 설정

sudo mkdir /backup
sudo chmod 700 /backup

sudo nano /root/docker-full-backup.sh
sudo chmod +x /root/docker-full-backup.sh

3-2. 수동 테스트 실행

sudo /root/docker-full-backup.sh

3-3. 실행 결과 확인

ls /backup

예시 결과:

/backup/YYYY-MM-DD-HHMM/
├── postgres/
├── mysql/
├── volumes/
└── meta/

4. 자동화 & 보관 정책

4-1. cron 자동 백업 (매일 새벽 3시)

sudo crontab -e

아래 줄 추가:

0 3 * * * /root/docker-full-backup.sh >> /var/log/docker-backup.log 2>&1

4-2. 보관 정책 (30일)

스크립트 내에 아래 명령이 포함되어 있어 30일 지난 백업은 자동 삭제됩니다.

find /backup -mindepth 1 -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \;

4-3. (선택) 월 1회 스냅샷 백업

재해복구용 Docker 엔진 전체 백업입니다. 짧은 다운타임이 발생합니다.

sudo systemctl stop docker
sudo tar --xattrs --acls -czvf /backup/docker-engine-$(date +%F).tar.gz /var/lib/docker
sudo systemctl start docker

👉 매일 할 필요 없으며, 월 1회면 충분합니다.


5. 복구 방법

새 서버에서 아래 순서로 복구합니다.

5-1. Docker 설치

공식 문서를 참고하여 Docker Engine을 설치합니다.

5-2. 백업 폴더 복사

USB 등에서 /backup/YYYY-MM-DD-HHMM 폴더를 서버로 복사합니다.

5-3. PostgreSQL 복구

cat my-app-db-prod.sql | docker exec -i my-app-db-prod psql -U postgres


5-4. MySQL 복구

cat my-mysql-01.sql | docker exec -i my-mysql-01 mysql -uroot -p

5-5. Volume 복구

docker run --rm -v nextcloud_data:/volume -v $(pwd):/backup alpine \
tar xzf /backup/nextcloud_data.tar.gz -C /volume



6. USB 외부 백업

백업 폴더를 USB 외장 매체로 안전하게 복사하는 절차입니다. (Ubuntu 24.04 기준)


6-1. USB 장치 확인

lsblk

예시 출력:

sda 8:0 0 1.8T 0 disk
├─sda1 8:1 0 512M 0 part
└─sda2 8:2 0 1.8T 0 part

sdb 8:16 1 58G 0 disk <-- ★ USB
└─sdb1 8:17 1 58G 0 part

👉 USB는 보통 sdb 또는 sdc 로 잡히며, sdb1 같은 파티션 이름을 사용합니다.

6-2. USB 마운트

sudo mkdir -p /mnt/usb
sudo mount /dev/sdb1 /mnt/usb

6-3. 마운트 확인

df -h | grep usb
# 또는
ls /mnt/usb


6-4. rsync로 복사 (필수)

절대 cp 명령을 쓰지 마세요. 권한이 깨집니다.
Docker / DB 백업은 반드시 rsync를 사용합니다.

sudo rsync -avh /backup/YYYY-MM-DD-HHMM /mnt/usb/

옵션

의미

-a

권한 / 소유자 / 심볼릭 링크 유지 (★ 핵심)

-v

진행상황 표시

-h

사람이 읽기 쉬운 용량 표시

다음 속성이 그대로 유지됩니다: root 권한, Docker volume 권한, DB 데이터 권한, tar 파일 속성, UID/GID, 심볼릭 링크


6-5. 복사 검증

du -sh /backup/YYYY-MM-DD-HHMM
du -sh /mnt/usb/YYYY-MM-DD-HHMM

두 값이 같으면 성공입니다.



6-6. 안전한 USB 제거

sync
sudo umount /mnt/usb

이후 USB를 물리적으로 분리합니다.


7. 주의사항 & 팁

🔥 절대 하면 안 되는 실수

cp -r /backup/...    # ❌ 권한 깨짐
mv /backup/...       # ❌ 원본 사라짐
tar 다시 묶기         # ❌ Docker 복구 실패 위험

Docker volume 백업 복사는 rsync만 사용하세요.


💡 tar 경고 메시지는 정상

tar: socket ignored

DBUS 소켓, 캐시 파일 등 런타임 전용 파일이라 무시해도 됩니다.


💡 Alpine 이미지 다운로드 메시지도 정상

Unable to find image 'alpine:latest'

Volume을 안전하게 읽기 위해 임시 Alpine 컨테이너를 띄우는 정석 방식입니다.


8. 백업 검증

📦 백업 폴더 구조

/backup/YYYY-MM-DD-HHMM/
├── postgres/        # PostgreSQL dump (.sql)
├── mysql/           # MySQL dump (.sql)
├── docker_volumes/  # 모든 Docker Volume tar.gz
├── metadata/        # 컨테이너/네트워크/이미지 목록
└── home_backup.tar  # 사용자 프로젝트 파일

👉 이 폴더 하나만 있으면 서버 전체 복구가 가능합니다.

🔎 복구 테스트 (권장)

백업 검증의 핵심은 "복구 테스트"입니다.

  1. 빈 테스트 서버 준비

  2. Docker 설치

  3. 백업 폴더 복사

  4. Volume 복원 후 컨테이너 실행

→ 서비스가 정상 기동되면 백업 100% 성공입니다.



✅ 요약

✔ DB: pg_dumpall / mysqldump 논리 백업 — 운영 중에도 안전
✔ Volume: Alpine 임시 컨테이너로 tar 압축 — 데이터 무결성 보장
✔ 메타데이터: 컨테이너 설정 전체 기록
✔ 프로젝트 파일: /home 전체 보존
✔ 30일 자동 정리 + cron 자동화
✔ USB 외부 복사는 rsync -avh 만 사용

👉 이 가이드를 따르면 Docker 환경을 완전히 복구할 수 있는 실전형 백업이 완성됩니다.


Comments

Log in to comment

Loading comments...
이전 글목록 보기다음 글

당신의 이야기를 기다리고 있습니다